package com.example.netcamerastreamdemo;

import android.content.Intent;
import android.media.MediaCodec;
import android.media.MediaFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;

import com.google.gson.Gson;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Hashtable;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.WebSocket;
import okhttp3.WebSocketListener;
import okio.ByteString;

import static android.media.MediaFormat.MIMETYPE_VIDEO_AVC;

@RequiresApi(api = Build.VERSION_CODES.O)
public class TestTimeActivity extends AppCompatActivity implements SurfaceHolder.Callback {
    private static final String TAG = "TestTimeActivity";

    WebSocket webSocket;
    Gson mGson = new Gson();
    static String dev_guid = "63-00F628C3B402-9A2A";
    static int video_chnn = 9;
    static int sub_chnn = 2;
    static String rec_path = "63-00F628C3B402-9A2A\\\\1623202389634\\\\63-00F628C3B402-9A2A_9_1623202389634";

    Hashtable<Integer, byte[]> mStreamData = new Hashtable<>();
    int mIndex = -1;
    SurfaceView surfaceView;
    DecodeThread decodeThread = new DecodeThread();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        surfaceView = findViewById(R.id.surface_view);
        surfaceView.getHolder().addCallback(this);
    }

    public void initWebSocket(View view){
        OkHttpClient mClient = new OkHttpClient.Builder()
                .readTimeout(3, TimeUnit.SECONDS)//设置读取超时时间
                .writeTimeout(3, TimeUnit.SECONDS)//设置写的超时时间
                .connectTimeout(3, TimeUnit.SECONDS)//设置连接超时时间
                .build();

        String url = "wss://shike-qa.video110.cn/nsdk";
        Request request = new Request.Builder().get().url(url).build();
        webSocket = mClient.newWebSocket(request, new WebSocketListener() {
            @Override
            public void onOpen(WebSocket webSocket, Response response) {
                super.onOpen(webSocket, response);
                Log.i(TAG, "---onOpen===");
            }

            @Override
            public void onMessage(WebSocket webSocket, String text) {
                super.onMessage(webSocket, text);
                Log.i(TAG, "---onMessage===" + text);
            }

            @Override
            public void onMessage(WebSocket webSocket, ByteString bytes) {
                super.onMessage(webSocket, bytes);
                Log.i(TAG, "---onMessage===" + mIndex);
                mIndex++;
                mStreamData.put(mIndex, bytes.substring(44).toByteArray());
            }

            @Override
            public void onClosing(WebSocket webSocket, int code, String reason) {
                super.onClosing(webSocket, code, reason);
                Log.i(TAG, "---onClosing===" + reason);
            }

            @Override
            public void onClosed(WebSocket webSocket, int code, String reason) {
                super.onClosed(webSocket, code, reason);
                Log.i(TAG, "---onClosed===" + reason);
            }

            @Override
            public void onFailure(WebSocket webSocket, Throwable t, Response response) {
                super.onFailure(webSocket, t, response);
                Log.i(TAG, "---onFailure===" + t.toString());
            }
        });
    }

    public void test1(View view){
        startActivity(new Intent(this, DecodeLocalMp4Activity.class));
    }

    public void stopWebsocket(View view){
        if (webSocket == null){
            return;
        }
        webSocket.cancel();
    }

    public void sendStartVideoMsg(View view){
        MsgData startVideoMsg = new MsgData(
                "VSDK_CMD_TX_RT_VIDEO_START",
                dev_guid,
                video_chnn,
                sub_chnn,
                rec_path);
        webSocket.send(mGson.toJson(startVideoMsg));
    }

    public void sendStopVideoMsg(View view){
        MsgData stopVideoMsg = new MsgData(
                "VSDK_CMD_TX_RT_VIDEO_STOP",
                dev_guid,
                video_chnn,
                sub_chnn,
                rec_path);
        webSocket.send(mGson.toJson(stopVideoMsg));
    }

    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        Log.i(TAG, "---surfaceCreated===");
        decodeThread.start();
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        Log.i(TAG, "---surfaceChanged===");

    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        Log.i(TAG, "---surfaceDestroyed===");
    }

    private class DecodeThread extends Thread{
        private MediaCodec decoder;
        int mWidth = 704;
        int mHeight = 576;
        int decodeCount = 0;
        boolean unFinish = true;

        @Override
        public void run() {
            while (decodeCount == 0){
                testDecode();
            }
        }

        private void testDecode(){
            Log.i(TAG, "---testDecode===");
            if (decoder == null){
                MediaFormat format = MediaFormat.createVideoFormat(MIMETYPE_VIDEO_AVC, mWidth, mHeight);
                try {
                    decoder = MediaCodec.createDecoderByType(MIMETYPE_VIDEO_AVC);
                    decoder.configure(format, surfaceView.getHolder().getSurface(), null, 0);
                    decoder.start();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            while (unFinish){
                if (null == mStreamData.get(decodeCount)){
                    continue;
                }
                byte[] frameByte = mStreamData.get(decodeCount).clone();
                int inputIndex = decoder.dequeueInputBuffer(10000);
                if (inputIndex >= 0){
                    ByteBuffer byteBuffer = decoder.getInputBuffer(inputIndex);
                    byteBuffer.put(frameByte);
                    decoder.queueInputBuffer(inputIndex, 0, frameByte.length, 0, 0);
                }
                MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
                int outputIndex = decoder.dequeueOutputBuffer(bufferInfo, 0);
                if (outputIndex >= 0){
                    decoder.releaseOutputBuffer(outputIndex, true);
                }
                mStreamData.remove(decodeCount);
                decodeCount++;
            }
        }
    }

    public static class MsgData{
        public MsgData(String cmd, String dev_guid, int video_chnn, int sub_chnn, String rec_path) {
            this.cmd = cmd;
            this.dev_guid = dev_guid;
            this.video_chnn = video_chnn;
            this.sub_chnn = sub_chnn;
            this.rec_path = rec_path;
        }

        String cmd;
        String dev_guid;
        int video_chnn;
        int sub_chnn;
        String rec_path;
    }
}